//------------------------------------------------------------------------
// Abstract: Implement of XString
//
// Authoring: XiaoHanxiong
//
// Time: 2014.03.21
//
// Static test:
//
// Version history:
//		Ver_1.0	: 2014.03.21	XiaoHanxiong
//------------------------------------------------------------------------
#include "stdafx.h"
#include "XString.h"


namespace Library
{	
	/*
		Forward Declaration
		_A: ASCII char version
		_W: Wide char version
	*/

	XString::XString()
	{

	}

	XString::~XString()
	{

	}

	/*
		Basic operation on string that consist of alphabet or number
		isAlpha:	is a alphabet
		isNumber:	is a number
		lower:		lower a case
		upper:		upper a case
	*/
	template<typename _Char>
	bool _tpl_isAlpha(const _Char _char)
	{
		if( (_Char('a') <= _char && _char <= _Char('z')) || 
			(_Char('A') <= _char && _char <= _Char('Z')) )
			return true;
		else return false;
	}

	template<typename _Char, typename _String>
	bool _tpl_isAlphaStr(const _String& _string)
	{
		for(_String::size_type n = 0; n < _string.size(); n++)
		{
			if( (_Char('a') <= _string[n] && _string[n] <= _Char('z')) || 
				(_Char('A') <= _string[n] && _string[n] <= _Char('Z')) )
				;// is char
			else return false;
		}
		return true;
	}

	template<typename _Char>
	bool _tpl_isNumber(const _Char _char)
	{
		if( _Char('0') <= _char && _char <= _Char('9') )
			return true;
		else return false;
	}

	template<typename _Char, typename _String>
	bool _tpl_isNumberStr(const _String& _string)
	{
		for(_String::size_type n = 0; n < _string.size(); n++)
		{
			if(_Char('0') <= _string[n] && _string[n] <= _Char('9') )
				;// is char
			else return false;
		}
		return true;
	}

	template<typename _Char>
	void _tpl_lowerCase(_Char _char)
	{
		if( _Char('A') <= _char && _char <= _Char('Z') )
			_char += 32;
	}
	
	template<typename _Char, typename _String>
	void _tpl_lowerCaseStr(_String& _string)
	{
		for(_String::size_type n = 0; n < _string.size(); n++)
		{
			if( _Char('a') <= _string[n] && _string[n] <= _Char('a') )
				_string[n] += 32;
		}
	}

	template<typename _Char>
	void _tpl_upperCase(_Char _char)
	{
		if( _Char('A') <= _char && _char <= _Char('Z') )
			_char += 32;
	}

	template<typename _Char, typename _String>
	void _tpl_upperCaseStr(_String& _string)
	{
		for(_String::size_type n = 0; n < _string.size(); n++)
		{
			if( _Char('a') <= _string[n] && _string[n] <= _Char('z') )
				_string[n] -= 32;
		}
	}

	bool XString::IsAlphaA( const string& str )
	{
		return _tpl_isAlphaStr<char,string>(str);
	}

	bool XString::IsAlphaA( const char ch )
	{
		return _tpl_isAlpha(ch);
	}

	bool XString::IsNumberA( const string& str )
	{
		return _tpl_isNumberStr<char,string>(str);
	}

	bool XString::IsNumberA( const char ch )
	{
		return _tpl_isAlpha(ch);
	}

	void XString::LowerA( string& str )
	{
		_tpl_lowerCaseStr<char,string>(str);
	}

	void XString::LowerA( char ch )
	{
		_tpl_lowerCase(ch);
	}

	void XString::UpperA( string& str )
	{
		_tpl_upperCaseStr<char,string>(str);
	}

	void XString::UpperA( char ch )
	{
		_tpl_upperCase(ch);
	}

	bool XString::IsAlphaW( const wstring& str )
	{
		return _tpl_isAlphaStr<wchar_t,wstring>(str);
	}

	bool XString::IsAlphaW( const wchar_t ch )
	{
		return _tpl_isAlpha(ch);
	}

	bool XString::IsNumberW( const wstring& str )
	{
		return _tpl_isNumberStr<wchar_t,wstring>(str);
	}

	bool XString::IsNumberW( const wchar_t ch )
	{
		return _tpl_isAlpha(ch);
	}

	void XString::LowerW( wstring& str )
	{
		_tpl_lowerCaseStr<wchar_t,wstring>(str);
	}

	void XString::LowerW( wchar_t ch )
	{
		_tpl_lowerCase(ch);
	}

	void XString::UpperW( wstring& str )
	{
		_tpl_upperCaseStr<wchar_t,wstring>(str);
	}

	void XString::UpperW( wchar_t ch )
	{
		_tpl_upperCase(ch);
	}


	void XString::FormatA( string& str, const char* format, ... )
	{
		char buffer[1024] = {0};
		va_list args;
		int n;

		va_start(args, format);
		n = vsprintf_s(buffer, format, args);
		va_end(args);
		str = buffer;
	}

	void XString::FormatW( wstring& str, const wchar_t* format, ... )
	{
		wchar_t buffer[1024] = {0};
		va_list args;
		int n;

		va_start(args, format);
		n = vswprintf_s(buffer, format, args);
		va_end(args);
		str = buffer;
	}

	/*
		Function: _tpl_toBinString
		Abstract: Convert a number to binary string
		_Num _num[in]:			input number
		_String& _string[out]:	output formate string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_toBinString( _Num _num, _String& _string )
	{
		_Num remain = 0;
		_string.clear();

		if(_num != 0)
		{
			while(_num != 0)
			{
				remain = _num % 2;
				_string.insert(_string.begin(), _Char('0' + remain));
				_num /= 2;
			}
		}
		else _string.push_back(_Char('0'));
	}

	/*
		Function: _tpl_toOctString
		Abstract: Convert a number to octal string
		_Num _num[in]:			input number
		_String& _string[out]:	output formate string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_toOctString( _Num _num, _String& _string )
	{
		_Num remain = 0;
		_string.clear();

		if(_num != 0)
		{
			while(_num != 0)
			{
				remain = _num % 8;
				_string.insert(_string.begin(), _Char('0' + remain));
				_num /= 8;
			}
		}
		else _string.push_back(_Char('0'));
	}

	/*
		Function: _tpl_toDecString
		Abstract: Convert a number to octal string
		_Num _num[in]:			input number
		_String& _string[out]:	output formate string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_toDecString( _Num _num, _String& _string )
	{
		_Num remain = 0;
		_string.clear();

		if(_num != 0)
		{
			while(_num != 0)
			{
				remain = _num % 10;
				if(remain < 10) _string.insert(_string.begin(), _Char('0' + remain));
				else _string.insert(_string.begin(), _Char('a' + remain));
				_num /= 10;
			}
		}
		else _string.push_back(_Char('0'));
	}

	/*
		Function: _tpl_toHexString
		Abstract: Convert a number to octal string
		_Num _num[in]:			input number
		_String& _string[out]:	output formate string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_toHexString( _Num _num, _String& _string )
	{
		_Num remain = 0;
		_string.clear();

		if(_num != 0)
		{
			while(_num != 0)
			{
				remain = _num % 16;
				if(0 <= remain && remain <= 9)
					_string.insert(_string.begin(), _Char('0' + remain));
				else 
					_string.insert(_string.begin(), _Char('a' + remain - 10));
				_num /= 16;
			}
		}
		else _string.push_back(_Char('0'));
	}

	//////////////////////////////////////////////////////////////////////////
	void XString::NumToBinStringA( unsigned short in, string& str )
	{
		_tpl_toBinString<unsigned short, string, char>(in, str);
	}

	void XString::NumToBinStringA( unsigned int in, string& str )
	{
		_tpl_toBinString<unsigned int, string, char>(in, str);
	}

	void XString::NumToBinStringA( unsigned __int64 in, string& str )
	{
		_tpl_toBinString<unsigned __int64, string, char>(in, str);
	}

	void XString::NumToBinStringW( unsigned short in, wstring& str )
	{
		_tpl_toBinString<unsigned short, wstring, wchar_t>(in, str);
	}

	void XString::NumToBinStringW( unsigned int in, wstring& str )
	{
		_tpl_toBinString<unsigned int, wstring, wchar_t>(in, str);
	}

	void XString::NumToBinStringW( unsigned __int64 in, wstring& str )
	{
		_tpl_toBinString<unsigned __int64, wstring, wchar_t>(in, str);
	}

	//////////////////////////////////////////////////////////////////////////
	void XString::NumToOctStringA( unsigned short in, string& str )
	{
		_tpl_toOctString<unsigned short, string, char>(in, str);
	}

	void XString::NumToOctStringA( unsigned int in, string& str )
	{
		_tpl_toOctString<unsigned int, string, char>(in, str);
	}

	void XString::NumToOctStringA( unsigned __int64 in, string& str )
	{
		_tpl_toOctString<unsigned __int64, string, char>(in, str);
	}

	void XString::NumToOctStringW( unsigned short in, wstring& str )
	{
		_tpl_toOctString<unsigned short, wstring, wchar_t>(in, str);
	}

	void XString::NumToOctStringW( unsigned int in, wstring& str )
	{
		_tpl_toOctString<unsigned int, wstring, wchar_t>(in, str);
	}

	void XString::NumToOctStringW( unsigned __int64 in, wstring& str )
	{
		_tpl_toOctString<unsigned __int64, wstring, wchar_t>(in, str);
	}

	//////////////////////////////////////////////////////////////////////////
	void XString::NumToDecStringA( unsigned short in, string& str )
	{
		_tpl_toDecString<unsigned short, string, char>(in, str);
	}

	void XString::NumToDecStringA( unsigned int in, string& str )
	{
		_tpl_toDecString<unsigned int, string, char>(in, str);
	}

	void XString::NumToDecStringA( unsigned __int64 in, string& str )
	{
		_tpl_toDecString<unsigned __int64, string, char>(in, str);
	}

	void XString::NumToDecStringA( float in, string& str )
	{
		int* _int_ptr = (int*)&in;
		int _int = *_int_ptr;
		_tpl_toDecString<unsigned int, string, char>(_int, str);
	}

	void XString::NumToDecStringA( double in, string& str )
	{
		__int64* _int_ptr = (__int64*)&in;
		__int64 _int = *_int_ptr;
		_tpl_toDecString<unsigned __int64, string, char>(_int, str);
	}

	void XString::NumToDecStringW( unsigned short in, wstring& str )
	{
		_tpl_toDecString<unsigned short, wstring, wchar_t>(in, str);
	}

	void XString::NumToDecStringW( unsigned int in, wstring& str )
	{
		_tpl_toDecString<unsigned int, wstring, wchar_t>(in, str);
	}

	void XString::NumToDecStringW( unsigned __int64 in, wstring& str )
	{
		_tpl_toDecString<unsigned __int64, wstring, wchar_t>(in, str);
	}

	void XString::NumToDecStringW( float in, wstring& str )
	{
		int* _int_ptr = (int*)&in;
		int _int = *_int_ptr;
		_tpl_toDecString<unsigned int, wstring, wchar_t>(_int, str);
	}

	void XString::NumToDecStringW( double in, wstring& str )
	{
		__int64* _int_ptr = (__int64*)&in;
		__int64 _int = *_int_ptr;
		_tpl_toDecString<unsigned __int64, wstring, wchar_t>(_int, str);
	}

	//////////////////////////////////////////////////////////////////////////
	void XString::NumToHexStringA( unsigned short in, string& str )
	{
		_tpl_toHexString<unsigned short, string, char>(in, str);
	}

	void XString::NumToHexStringA( unsigned int in, string& str )
	{
		_tpl_toHexString<unsigned int, string, char>(in, str);
	}

	void XString::NumToHexStringA( unsigned __int64 in, string& str )
	{
		_tpl_toHexString<unsigned __int64, string, char>(in, str);
	}

	void XString::NumToHexStringW( unsigned short in, wstring& str )
	{
		_tpl_toHexString<unsigned short, wstring, wchar_t>(in, str);
	}

	void XString::NumToHexStringW( unsigned int in, wstring& str )
	{
		_tpl_toHexString<unsigned int, wstring, wchar_t>(in, str);
	}

	void XString::NumToHexStringW( unsigned __int64 in, wstring& str )
	{
		_tpl_toHexString<unsigned __int64, wstring, wchar_t>(in, str);
	}


	/*
		Function: _tpl_tranBinToNum
		Abstract: Convert binary string to number
		_Num _num[out]:			output number
		_String& _string[in]:	input binary string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_tranBinToNum(_Num& _num, _String& _string)
	{
		_String::reverse_iterator itr = _string.rbegin();
		_String::size_type multi = 0;
		_Num tmp_num = 0;

		_num = 0;
		for( ; itr != _string.rend(); itr++, multi++ )
		{
			if(*itr == _Char('0')) ;
			else if(*itr == _Char('1')) tmp_num |= ((_Num)0x1) << multi;
			else return;
		}
		_num = tmp_num;
	}

	/*
		Function: _tpl_tranOctToNum
		Abstract: Convert octal string to number
		_Num _num[out]:			output number
		_String& _string[in]:	input octal string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_tranOctToNum(_Num& _num, _String& _string)
	{
		_String::reverse_iterator itr = _string.rbegin();
		_String::size_type multi = 0;
		_Num tmp_num = 0;

		_num = 0;
		for( ; itr != _string.rend(); itr++, multi+=3 )
		{
			if(*itr >= _Char('0') && *itr <= _Char('8'))  
				tmp_num |= (_Num)(*itr - _Char('0')) << multi;
			else return;
		}
		_num = tmp_num;
	}

	/*
		Function: _tpl_tranDecToNum
		Abstract: Convert decimal string to number
		_Num _num[out]:			output number
		_String& _string[in]:	input decimal string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_tranDecToNum(_Num& _num, _String& _string)
	{
		_String::reverse_iterator itr = _string.rbegin();
		_String::size_type multi = 1;
		_Num tmp_num = 0;

		_num = 0;
		for( ; itr != _string.rend(); itr++, multi*=10 )
		{
			if(*itr >= _Char('0') && *itr <= _Char('9'))  
				tmp_num += ((_Num)(*itr - _Char('0'))) * (_Num)multi;
			else return;
		}
		_num = tmp_num;
	}

	/*
		Function: _tpl_tranHexToNum
		Abstract: Convert hex string to number
		_Num _num[out]:			output number
		_String& _string[in]:	input hex string
	*/
	template<typename _Num, typename _String, typename _Char>
	void _tpl_tranHexToNum(_Num& _num, _String& _string)
	{
		_String::reverse_iterator itr = _string.rbegin();
		_String::size_type multi = 0;
		_Num tmp_num = 0;

		_num = 0;
		for( ; itr != _string.rend(); itr++, multi+=4 )
		{
			if(*itr >= _Char('0') && *itr <= _Char('9'))  tmp_num |= (_Num)(*itr - _Char('0')) << multi;
			else if(*itr >= _Char('a') && *itr <= _Char('f')) tmp_num |= (_Num)(*itr - _Char('a') + 10) << multi;
			else if(*itr >= _Char('A') && *itr <= _Char('F')) tmp_num |= (_Num)(*itr - _Char('A') + 10) << multi;
			else return;
		}
		_num = tmp_num;
	}

	//////////////////////////////////////////////////////////////////////////
	void XString::BinStringToNumA( string& str, short& out )
	{
		_tpl_tranBinToNum<short, string, char>(out, str);
	}

	void XString::BinStringToNumA( string& str, unsigned short& out )
	{
		_tpl_tranBinToNum<unsigned short, string, char>(out, str);
	}

	void XString::BinStringToNumA( string& str, int& out )
	{
		_tpl_tranBinToNum<int, string, char>(out, str);
	}

	void XString::BinStringToNumA( string& str, unsigned int& out )
	{
		_tpl_tranBinToNum<unsigned int, string, char>(out, str);
	}

	void XString::BinStringToNumA( string& str, __int64& out )
	{
		_tpl_tranBinToNum<__int64, string, char>(out, str);
	}

	void XString::BinStringToNumA( string& str, unsigned __int64& out )
	{
		_tpl_tranBinToNum<unsigned __int64, string, char>(out, str);
	}

	void XString::BinStringToNumW( wstring& str, short& out )
	{
		_tpl_tranBinToNum<short, wstring, wchar_t>(out, str);
	}

	void XString::BinStringToNumW( wstring& str, unsigned short& out )
	{
		_tpl_tranBinToNum<unsigned short, wstring, wchar_t>(out, str);
	}

	void XString::BinStringToNumW( wstring& str, int& out )
	{
		_tpl_tranBinToNum<int, wstring, wchar_t>(out, str);
	}

	void XString::BinStringToNumW( wstring& str, unsigned int& out )
	{
		_tpl_tranBinToNum<unsigned int, wstring, wchar_t>(out, str);
	}

	void XString::BinStringToNumW( wstring& str, __int64& out )
	{
		_tpl_tranBinToNum<__int64, wstring, wchar_t>(out, str);
	}

	void XString::BinStringToNumW( wstring& str, unsigned __int64& out )
	{
		_tpl_tranBinToNum<unsigned __int64, wstring, wchar_t>(out, str);
	}

	//////////////////////////////////////////////////////////////////////////
	void XString::OctStringToNumA( string& str, short& out )
	{
		_tpl_tranOctToNum<short, string, char>(out, str);
	}

	void XString::OctStringToNumA( string& str, unsigned short& out )
	{
		_tpl_tranOctToNum<unsigned short, string, char>(out, str);
	}

	void XString::OctStringToNumA( string& str, int& out )
	{
		_tpl_tranOctToNum<int, string, char>(out, str);
	}

	void XString::OctStringToNumA( string& str, unsigned int& out )
	{
		_tpl_tranOctToNum<unsigned int, string, char>(out, str);
	}

	void XString::OctStringToNumA( string& str, __int64& out )
	{
		_tpl_tranOctToNum<__int64, string, char>(out, str);
	}

	void XString::OctStringToNumA( string& str, unsigned __int64& out )
	{
		_tpl_tranOctToNum<unsigned __int64, string, char>(out, str);
	}

	void XString::OctStringToNumW( wstring& str, short& out )
	{
		_tpl_tranOctToNum<short, wstring, wchar_t>(out, str);
	}

	void XString::OctStringToNumW( wstring& str, unsigned short& out )
	{
		_tpl_tranOctToNum<unsigned short, wstring, wchar_t>(out, str);
	}

	void XString::OctStringToNumW( wstring& str, int& out )
	{
		_tpl_tranOctToNum<int, wstring, wchar_t>(out, str);
	}

	void XString::OctStringToNumW( wstring& str, unsigned int& out )
	{
		_tpl_tranOctToNum<unsigned int, wstring, wchar_t>(out, str);
	}

	void XString::OctStringToNumW( wstring& str, __int64& out )
	{
		_tpl_tranOctToNum<__int64, wstring, wchar_t>(out, str);
	}

	void XString::OctStringToNumW( wstring& str, unsigned __int64& out )
	{
		_tpl_tranOctToNum<unsigned __int64, wstring, wchar_t>(out, str);
	}

	//////////////////////////////////////////////////////////////////////////
	void XString::DecStringToNumA( string& str, short& out )
	{
		_tpl_tranDecToNum<short, string, char>(out, str);
	}

	void XString::DecStringToNumA( string& str, unsigned short& out )
	{
		_tpl_tranDecToNum<unsigned short, string, char>(out, str);
	}

	void XString::DecStringToNumA( string& str, int& out )
	{
		_tpl_tranDecToNum<int, string, char>(out, str);
	}

	void XString::DecStringToNumA( string& str, unsigned int& out )
	{
		_tpl_tranDecToNum<unsigned int, string, char>(out, str);
	}

	void XString::DecStringToNumA( string& str, __int64& out )
	{
		_tpl_tranDecToNum<__int64, string, char>(out, str);
	}

	void XString::DecStringToNumA( string& str, unsigned __int64& out )
	{
		_tpl_tranDecToNum<unsigned __int64, string, char>(out, str);
	}

	//void Format::DecStringToNumA( string& str, float& out )
	//{
	//	std::stringstream sbuffer;
	//	sbuffer.str(str);
	//	if(sbuffer >> out) ;
	//	else out = 0;
	//}

	//void Format::DecStringToNumA( string& str, double& out )
	//{
	//	std::stringstream sbuffer;
	//	sbuffer.str(str);
	//	if(sbuffer >> out) ;
	//	else out = 0;
	//}

	void XString::DecStringToNumW( wstring& str, short& out )
	{
		_tpl_tranDecToNum<short, wstring, wchar_t>(out, str);
	}

	void XString::DecStringToNumW( wstring& str, unsigned short& out )
	{
		_tpl_tranDecToNum<unsigned short, wstring, wchar_t>(out, str);
	}

	void XString::DecStringToNumW( wstring& str, int& out )
	{
		_tpl_tranDecToNum<int, wstring, wchar_t>(out, str);
	}

	void XString::DecStringToNumW( wstring& str, unsigned int& out )
	{
		_tpl_tranDecToNum<unsigned int, wstring, wchar_t>(out, str);
	}

	void XString::DecStringToNumW( wstring& str, __int64& out )
	{
		_tpl_tranDecToNum<__int64, wstring, wchar_t>(out, str);
	}

	void XString::DecStringToNumW( wstring& str, unsigned __int64& out )
	{
		_tpl_tranDecToNum<unsigned __int64, wstring, wchar_t>(out, str);
	}

	////////////////////////////////////////////////////////////////////////
	void XString::HexStringToNumA( string& str, short& out )
	{
		_tpl_tranHexToNum<short, string, char>(out, str);
	}

	void XString::HexStringToNumA( string& str, unsigned short& out )
	{
		_tpl_tranHexToNum<unsigned short, string, char>(out, str);
	}

	void XString::HexStringToNumA( string& str, int& out )
	{
		_tpl_tranHexToNum<int, string, char>(out, str);
	}

	void XString::HexStringToNumA( string& str, unsigned int& out )
	{
		_tpl_tranHexToNum<unsigned int, string, char>(out, str);
	}

	void XString::HexStringToNumA( string& str, __int64 & out )
	{
		_tpl_tranHexToNum<__int64, string, char>(out, str);
	}

	void XString::HexStringToNumA( string& str, unsigned __int64& out )
	{
		_tpl_tranHexToNum<unsigned __int64, string, char>(out, str);
	}

	void XString::HexStringToNumW( wstring& str, short& out )
	{
		_tpl_tranHexToNum<short, wstring, wchar_t>(out, str);
	}

	void XString::HexStringToNumW( wstring& str, unsigned short& out )
	{
		_tpl_tranHexToNum<unsigned short, wstring, wchar_t>(out, str);
	}

	void XString::HexStringToNumW( wstring& str, int& out )
	{
		_tpl_tranHexToNum<int, wstring, wchar_t>(out, str);
	}

	void XString::HexStringToNumW( wstring& str, unsigned int& out )
	{
		_tpl_tranHexToNum<unsigned int, wstring, wchar_t>(out, str);
	}

	void XString::HexStringToNumW( wstring& str, __int64 & out )
	{
		_tpl_tranHexToNum<__int64, wstring, wchar_t>(out, str);
	}

	void XString::HexStringToNumW( wstring& str, unsigned __int64& out )
	{
		_tpl_tranHexToNum<unsigned __int64, wstring, wchar_t>(out, str);
	}


	/*
		Function: _tpl_trimString
		Abstract: Trim a string to remain alphabet and number
		_String& _string[in][out]:	input/output string
	*/
	template<typename _String, typename _Char>
	void _tpl_trimString(_String& _string)
	{
		_String::size_type n = 0;
		while(n < _string.size())
		{
			if( (_Char('a') <= _string[n] && _string[n] <= _Char('z')) || 
				(_Char('A') <= _string[n] && _string[n] <= _Char('Z')) ||
				(_Char('0') <= _string[n] && _string[n] <= _Char('9')) ||
				_string[n] == _Char('_') )
				n++;// is alphabet/number
			else _string.erase(n, 1);
		}
	}

	/*
		Function: _tpl_trimStringRemain
		Abstract: Trim a string to remain specify char in another string
		_String& _string[in][out]:	input/output string
		_String& remain[in]:		remain char(in string)
	*/
	template<typename _String, typename _Char>
	void _tpl_trimStringRemain(_String& _string, _String& remain)
	{
		_String::size_type n = 0;
		while(n < _string.size())
		{
			if(remain.find(_string[n]) != _String::npos)
				n++;// the char is in 'remain', keep it
			else _string.erase(n, 1);
		}
	}

	/*
		Function: _tpl_trimStringExclude
		Abstract: Trim a string to exclude specify in another string
		_String& _string[in][out]:	input/output string
		_String& exclude[in]:		exclude char(in string)
	*/
	template<typename _String, typename _Char>
	void _tpl_trimStringExclude(_String& _string, _String& exclude)
	{
		_String::size_type n = 0;
		while(n < _string.size())
		{
			if(exclude.find(_string[n]) == _String::npos)
				n++;// the char is not in exclude, keep it
			else _string.erase(n, 1);
		}
	}

	void XString::TrimA( string& str )
	{
		_tpl_trimString<string, char>(str);
	}

	void XString::TrimW( wstring& str )
	{
		_tpl_trimString<wstring, wchar_t>(str);
	}

	void XString::TrimReA( string& str, string& remain )
	{
		_tpl_trimStringRemain<string, char>(str, remain);
	}

	void XString::TrimExA( string& str, string& exclude )
	{
		_tpl_trimStringExclude<string, char>(str, exclude);
	}

	void XString::TrimReW( wstring& str, wstring& remain )
	{
		_tpl_trimStringRemain<wstring, wchar_t>(str, remain);
	}

	void XString::TrimExW( wstring& str, wstring& exclude )
	{
		_tpl_trimStringExclude<wstring, wchar_t>(str, exclude);
	}


	/*
		Function: _tpl_replace
		Abstract: Replace the string by specify
		_String& _string[in][out]:	input/output string
		_String& _replace[in]:		the string will be replaced
		_String& _specify[in]:		the string will replace the other
	*/
	template<typename _String>
	void _tpl_replace( _String& _string, _String& _replace, _String& _specify )
	{
		_String::size_type pos = _string.find(_replace);
		_String::size_type size = _replace.size();
		if(pos != _String::npos)
		{
			_string.erase(pos, size);
			_string.insert(pos, _specify);
		}
	}

	void XString::ReplaceA( string& str, string& replace, string& specify )
	{
		_tpl_replace<string>(str, replace, specify);
	}

	void XString::ReplaceW( wstring& str, wstring& replace, wstring& specify )
	{
		_tpl_replace<wstring>(str, replace, specify);
	}


	/*
		Wide Char <==> Multi Char
	*/
	void XString::ConvertChar_MultiToWide( string& in, wstring& out )
	{
		const char* pSrc = in.c_str();
		size_t src_size = in.size();
		wchar_t* pDest = new wchar_t[src_size + 1]();
	#ifdef _WINNLS_ // Windows APIs header
		MultiByteToWideChar(CP_ACP, 0, pSrc, /*-1*/src_size, pDest, src_size + 1);
	#else
		setlocale(LC_ALL,"chs");
		mbstowcs_s(&src_size, pDest, src_size + 1, pSrc, src_size);
		setlocale(LC_ALL,"C");
	#endif
		out = pDest;
		delete[] pDest;
	}

	void XString::ConvertChar_WideToMulti( wstring& in, string& out )
	{
		const wchar_t* pSrc = in.c_str();
		size_t src_size = in.size();
		char* pDest = new char[src_size*2 + 1]();
	#ifdef _WINNLS_ // Windows APIs header
		BOOL flag = FALSE;
		WideCharToMultiByte(CP_ACP, 0, pSrc, src_size, pDest, src_size*2 + 1, NULL, &flag);
	#else
		setlocale(LC_ALL,"chs");
		wcstombs_s(&src_size, pDest, src_size*2 + 1, pSrc, _TRUNCATE);
		setlocale(LC_ALL,"C");
	#endif
		out = pDest;
		delete[] pDest;
	}


	/*
		Function: _tpl_split
		Abstract: Split a string with specify char
		_String& _string[in]:					input string
		vector<_String>& _string_vec[out]:		output string vector
		_Char splitter[in]:						splitter char
	*/
	template<typename _String, typename _Char>
	void _tpl_split(_String& _string, vector<_String>& _string_vec, _Char splitter)
	{
		_String::size_type begin = 0;
		_String::size_type end = _string.find_first_of(splitter, begin);
		while(end != _String::npos)
		{
			_String str(_string, begin, end - begin);
			_string_vec.push_back(str);
			begin = end + 1;
			end = _string.find_first_of(splitter, begin);
		}
		_String str(_string, begin, _string.size() - begin);
		_string_vec.push_back(str);
	}

	void XString::SplitA( string& in, vector<string>& out, char splitter )
	{
		_tpl_split<string, char>(in, out, splitter);
	}

	void XString::SplitW( wstring& in, vector<wstring>& out, wchar_t splitter )
	{
		_tpl_split<wstring, wchar_t>(in, out, splitter);
	}


	/*
		Function: _tpl_split2
		Abstract: Split a string with specify splitter and outer char
		_String& _string[in]:					input string
		vector<_String>& _string_vec[out]:		output string vector
		_Char _splitter[in]:					splitter char
		_Char _outer[in]:						a double char around each string
	*/
	template<typename _String, typename _Char>
	void _tpl_split2( _String& _string, vector<_String>& _string_vec, _Char splitter, _Char _outer )
	{
		_String::size_type begin = 0;
		_String::size_type end = _string.find_first_of(splitter, begin);
		_String::size_type size = _string.size();

		if(size == 0) return;
		while(end != _String::npos)
		{
			if(_string[begin] == _outer && _string[end - 1] == _outer)
			{
				_String str(_string, begin + 1, end - begin - 2);
				_string_vec.push_back(str);
				begin = end + 1;
				end = _string.find_first_of(splitter, begin);
			}
			else end = _string.find_first_of(splitter, end + 1);
		}

		if(_string[begin] == _outer && _string[size - 1] == _outer)
		{
			_String str(_string, begin + 1, _string.size() - begin - 2);
			_string_vec.push_back(str);
		}
	}

	void XString::SplitA( string& in, vector<string>& out, char splitter, char outer )
	{
		_tpl_split2<string, char>(in, out, splitter, outer);
	}

	void XString::SplitW( wstring& in, vector<wstring>& out, wchar_t splitter, wchar_t outer )
	{
		_tpl_split2<wstring, wchar_t>(in, out, splitter, outer);
	}

	/*
		Function: _tpl_floatPointStringToNum
		Abstract: convert float string to number
		_String& _string[in]:		input string
		_Number& _number[out]:		output number
	*/
	template<typename _String, typename _Number, typename _Char>
	void _tpl_floatPointStringToNum(_String& _string, _Number& _number)
	{
		typedef std::basic_stringstream<_Char, char_traits<_Char>, allocator<_Char>> xstringstream;
		xstringstream sbuffer;
		sbuffer.str(_string);
		sbuffer >> _number;
	}

	/*
		Function: _tpl_NumTofloatPointString
		Abstract: convert float string to number
		_String& _string[out]:		output string
		_Number _number[int]:		input number
	*/
	template<typename _String, typename _Number, class _Char>
	void _tpl_NumTofloatPointString( _Number _number, _String& _string)
	{
		typedef std::basic_stringstream<_Char, char_traits<_Char>, allocator<_Char>> xstringstream;
		xstringstream sbuffer;
		sbuffer << _number;
		_string = sbuffer.str();
	}

	void XString::FloatStringToNumA( string& str, float& out )
	{
		_tpl_floatPointStringToNum<string, float, char>(str, out);
	}

	void XString::FloatStringToNumW( wstring& str, float& out )
	{
		_tpl_floatPointStringToNum<wstring, float, wchar_t>(str, out);
	}

	void XString::DoubleStringToNumA( string& str, double& out )
	{
		_tpl_floatPointStringToNum<string, double, char>(str, out);
	}

	void XString::DoubleStringToNumW( wstring& str, double& out )
	{
		_tpl_floatPointStringToNum<wstring, double, wchar_t>(str, out);
	}

	void XString::NumToFloatStringA( float in, string& str )
	{
		_tpl_NumTofloatPointString<string, float, char>(in, str);
	}

	void XString::NumToFloatStringW( float in, wstring& str )
	{
		_tpl_NumTofloatPointString<wstring, float, wchar_t>(in, str);
	}

	void XString::NumToDoubleStringA( double in, string& str )
	{
		_tpl_NumTofloatPointString<string, double, char>(in, str);
	}

	void XString::NumToDoubleStringW( double in, wstring& str )
	{
		_tpl_NumTofloatPointString<wstring, double, wchar_t>(in, str);
	}

	/*
		For reading UTF-8 encoding files
		UTF8ToNormalW: convert UTF-8 string to normal wide char string(wstring)
		UTF8ToNormalA: convert UTF-8 string to normal char string(string)
		Note: The two method need WinNls.h
	*/
#if defined(WIN32) && defined(_WINNLS_)
	void XString::UTF8ToNormalW( void* ptr, size_t size, wstring& str )
	{
		wchar_t* buffer = new wchar_t[size + 1]();
		MultiByteToWideChar(CP_UTF8, 0, (char*)ptr, /*-1*/size, buffer, size + 1);
		str = buffer;
		delete [] buffer;
	}

	void XString::UTF8ToNormalA( void* ptr, size_t size, string& str )
	{
		wchar_t* buffer = new wchar_t[size + 1]();
		char* pDest = new char[size*2 + 1]();
		BOOL flag = FALSE;

		MultiByteToWideChar(CP_UTF8, 0, (char*)ptr, /*-1*/size, buffer, size + 1);
		WideCharToMultiByte(CP_ACP, 0, buffer, size+1, pDest, size*2 + 1, NULL, &flag);
		str = pDest;
		delete [] buffer;
		delete [] pDest;
	}
#endif // defined(WIN32) && defined(_WINNLS_)

}// _Library
